package com.cskaoyan.config;

import com.cskaoyan.realm.AdminRealm;
import com.cskaoyan.realm.WxRealm;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.LinkedHashMap;

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 认证失败后重定向的url
        shiroFilterFactoryBean.setLoginUrl("/unAuthc");

        // 对请求过滤
        // 注意要使用LinkedHashMap，因为过滤是有顺序的
        LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
        // 注意"/**", "authc" 放最后面
        filterMap.put("/admin/auth/login", "anon");  // 登陆请求可以匿名访问
        // filterMap.put("/admin/auth/info", "anon");  // 登陆请求可以匿名访问

        // filterMap.put("/unAuthc", "anon");  // 登陆请求可以匿名访问
        // filterMap.put("/storage/fetch/*", "anon");  // 可以匿名访问图片

        filterMap.put("/admin/**", "authc");  // 其它所有admin请求都必须通过认证

        filterMap.put("/wx/cart/*", "authc");  // 其它所有admin请求都必须通过认证
        filterMap.put("/wx/user/*", "authc");  // 其它所有admin请求都必须通过认证
        filterMap.put("/wx/collect/*", "authc");  // 其它所有admin请求都必须通过认证
        filterMap.put("/wx/address/*", "authc");  // 其它所有admin请求都必须通过认证
        filterMap.put("/wx/order/*", "authc");  // 其它所有admin请求都必须通过认证
        filterMap.put("/wx/feedback/*", "authc");  // 其它所有admin请求都必须通过认证
        filterMap.put("/wx/footprint/*", "authc");  // 其它所有admin请求都必须通过认证
        //
        // filterMap.put("/wx/coupon/list", "anon");
        // filterMap.put("/wx/coupon/*", "authc");  // 其它所有admin请求都必须通过认证






        // filterMap.put("/admin/auth/logout", "logout");  // 也可以在这里通过filter写logout，但是建议在controller写，因为可以增加登出的log日志

        // setFilterChainDefinitionMap()形参为map：key--请求url，value--过滤器
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;
    }

    // shiro 核心组件：SecurityManager
    @Bean
    public DefaultWebSecurityManager securityManager(AdminRealm adminRealm, WxRealm wxRealm, CustomAuthenticator customAuthenticator) {
        // public DefaultWebSecurityManager securityManager(AdminRealm adminRealm, CustomAuthenticator customAuthenticator) {

        // 配置自定义realm
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        // defaultWebSecurityManager.setRealm(adminRealm);
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(wxRealm);
        defaultWebSecurityManager.setRealms(realms);

        defaultWebSecurityManager.setSessionManager(webSessionManager());  // 也可以像上面的写法一样，写在形参中
        defaultWebSecurityManager.setAuthenticator(customAuthenticator);
        return defaultWebSecurityManager;
    }

    // 声明式鉴权（即注解）需要的组件
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public DefaultWebSessionManager webSessionManager() {
        CustomSessionManager customSessionManager = new CustomSessionManager();
        // 设置session的过期时间，单位：毫秒
        // customSessionManager.setGlobalSessionTimeout(1000000);

        // 删除失效的session
        customSessionManager.setDeleteInvalidSessions(true);
        return customSessionManager;
    }

    // 要注册到SecurityManager中
    @Bean
    public CustomAuthenticator authenticator(AdminRealm adminRealm, WxRealm wxRealm) {
        CustomAuthenticator customAuthenticator = new CustomAuthenticator();
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(wxRealm);
        customAuthenticator.setRealms(realms);
        return customAuthenticator;
    }


}
